/*
    Main unit for OBME submodules.  Handles:
    -   Initialization (writing hooks & patches)
    -   global debugging log (linked to log in loader)
    -   global Submodule interface
    -   global module handle

    This example plugin has two submodule DLLs - one for the CS, and one for the game.  
    This is necessary because the game and CS use slightly different definitions for many COEF classes.
    However, there is (usually) a lot of overlap between the code for the two.
    The best all-around solution, to minimize redefinition and the hassle similar but separate VS projects,
    is to use a single 'Submodule' project that compiles as the CS submodule under the 'Debug_CS' and 'Release_CS' 
    configurations, but compiles as the Game submodule under the 'Debug_Game' and 'Release_Game' configurations.
    IMPORTANT: this project must be compiled *twice*, once using a 'CS' configuration, and once using a 'Game'
    configuration.  One will generate a 'CS' dll, and the other a 'Game' dll. 
*/
#include "Components/EventManager.h"
#include "Submodule/Interface.h"
#include "Submodule/Globals.h"
#include "Submodule/EffectItemGenerator.h"
#include "Submodule/MagicItemGenerator.h"
#include "Submodule/AffixFilter.h"
#include "Submodule/Generation.h"

#include "API/TES/TESDataHandler.h"
#include "API/CSDialogs/ObjectWindow.h"

/*--------------------------------------------------------------------------------------------*/
// global debugging log for the submodule
_declspec(dllimport) OutputLog _gLog;
OutputLog& gLog = _gLog;

/*--------------------------------------------------------------------------------------------*/
// global submodule interface
SubmoduleInterface  g_submoduleIntfc;
// module (or "instance") handle - necessary for accessing embedded resources, e.g. dialog templates
HMODULE hModule = 0;

/*--------------------------------------------------------------------------------------------*/
// submodule initialization
extern "C" _declspec(dllexport) void* Initialize(obseIntfcFunctor::obseFunction* scriptCaller, obseIntfcFunctor::obseFunction* soulLvFromLL, obseIntfcFunctor::obseFunction* saveFunction)
{   
    // begin initialization  
    _MESSAGE("Initializing Submodule ...");

	// Set script executor
	callScptNoArgs.function = scriptCaller;
	getSoulLvFromLL.function = soulLvFromLL;
	addFormToSavegame.function = saveFunction;

	// Set callbacks
	EventManager::DataHandler::CreateDefaults.RegisterCallback(Souls::Initialize);
	EventManager::DataHandler::Clear.RegisterCallback(Souls::Clear);

#ifdef OBLIVION
	EventManager::GameWorld::EvaluateContainer.RegisterCallback(Generation::ProcessContainer);
#endif

	// compatibility with old injection method
	if (TESDataHandler::dataHandler)
	{
		Souls::Initialize();
#ifndef OBLIVION
		// Force update of object window, so that new spell will appear.
		// Depending on the type of forms we are creating, we may need to do other post-processing. 
		//SendMessage(ObjectWindow::objectWindowHandle,ObjectWindow::WM_REFRESHLIST,0,0);
#endif
	}

    // Perform hooks & patches
    MagicItemGenerator::InitializeMagicItemGenerator();
	AffixFilter::InitializeAffixFilter();
    
    // initialization complete
    _DMESSAGE("Submodule initialization completed sucessfully");
    return &g_submoduleIntfc;
}

/*--------------------------------------------------------------------------------------------*/
// submodule loading
#ifndef MFC
// Project uses standard windows libraries, define an entry point for the DLL to handle loading/unloading
BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
//	_MESSAGE("DllMain called.");
	switch(dwReason)
	{
	case DLL_PROCESS_ATTACH:    // dll loaded
		hModule = (HMODULE)hDllHandle;  // store module handle
//		MessageBox(NULL, "ARES submodule is attached, attach debugger now.", "Submodule Attached", MB_OK|MB_ICONEXCLAMATION);
		_MESSAGE("Attaching Submodule ..."); 
		break;
	case DLL_PROCESS_DETACH:    // dll unloaded
		_MESSAGE("Detaching Submodule ...");      
		break;
	}   
	return true;
}
#else
// Project uses MFC, we define here an instance of CWinApp to make this a 'well-formed' DLL
class CSubmoduleApp : public CWinApp
{
public:
	virtual BOOL InitInstance()
	{// dll loaded
		hModule = m_hInstance;  // store module handle
//		MessageBox(NULL, "ARES submodule is attached, attach debugger now.", "Submodule Attached", MB_OK|MB_ICONEXCLAMATION);
		_MESSAGE("Attaching Submodule ...");
		return true;
	}
	virtual int ExitInstance()
	{// dll unloaded
//       _MESSAGE("Detaching Submodule ...");      
		return CWinApp::ExitInstance();
	}
} gApp;
#endif
